#!/usr/bin/env node
/*
 * Data sync script for menu categories, images and menu items
 * - Logs in as admin to obtain token
 * - Ensures 7 categories exist with correct sort order
 * - Syncs menu items from iOS MenuConfig.swift 
 * - Copies iOS Assets.xcassets images into backend uploads/menu-images
 */

require('dotenv').config();
const axios = require('axios');
const fs = require('fs');
const path = require('path');

const BASE_URL = process.env.BACKEND_URL || 'http://localhost:3000';
const ADMIN_EMAIL = process.env.ADMIN_EMAIL || 'admin@example.com';
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || '123456';

// 新增：可选开关控制执行部分
const SYNC_IMAGES = process.env.SYNC_IMAGES !== 'false';
const SYNC_ITEMS = process.env.SYNC_ITEMS !== 'false';

const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
const ASSETS_DIR = path.resolve(PROJECT_ROOT, 'CMB250716', 'Assets.xcassets');
const UPLOADS_DIR = path.resolve(__dirname, '..', 'uploads', 'menu-images');

const categoriesConfig = [
  { name: '推荐', name_en: 'Must Try', sort_order: 1, is_active: true },
  { name: '促销', name_en: 'Promo', sort_order: 2, is_active: true },
  { name: '套餐', name_en: 'Set', sort_order: 3, is_active: true },
  { name: '主菜', name_en: 'Main Dishes', sort_order: 4, is_active: true },
  { name: '配菜', name_en: 'Side Dishes', sort_order: 5, is_active: true },
  { name: '炸鸡', name_en: 'Fried Chicken', sort_order: 6, is_active: true },
  { name: '饮品', name_en: 'Drinks', sort_order: 7, is_active: true }
];

// iOS 分类名映射到后端分类ID
const categoryNameToId = new Map();

function logStep(title) {
  console.log(`\n==== ${title} ====`);
}

async function loginAndGetToken() {
  logStep('Admin Login');
  const url = `${BASE_URL}/api/auth/login`;
  try {
    const res = await axios.post(url, {
      email: ADMIN_EMAIL,
      password: ADMIN_PASSWORD,
      remember_me: true
    }, { timeout: 15000 });

    if (!res.data || !res.data.success) {
      throw new Error('Login response not successful');
    }
    const token = res.data.data && res.data.data.token;
    if (!token) throw new Error('Token not found in response');
    console.log('Login successful.');
    return token;
  } catch (err) {
    console.error('Login failed:', err.response?.data || err.message);
    throw err;
  }
}

async function ensureCategories(token) {
  logStep('Ensuring Categories');
  const api = axios.create({
    baseURL: `${BASE_URL}/api/menu`,
    headers: { Authorization: `Bearer ${token}` },
    timeout: 20000
  });

  // Fetch existing
  const existingRes = await api.get('/categories');
  const existing = Array.isArray(existingRes.data?.data) ? existingRes.data.data : [];

  // Build lookup by both zh and en names
  const byZh = new Map(existing.map(c => [String(c.name).trim(), c]));
  const byEn = new Map(existing.map(c => [String(c.name_en || '').trim(), c]));

  const createdOrExisting = [];

  for (const cfg of categoriesConfig) {
    const found = byZh.get(cfg.name) || (cfg.name_en ? byEn.get(cfg.name_en) : undefined);
    if (found) {
      createdOrExisting.push(found);
      categoryNameToId.set(cfg.name, found.id);
      // 更新 name/name_en/is_active 三者的偏差
      const needsUpdate = (found.name !== cfg.name) || (found.name_en !== cfg.name_en) || (found.is_active !== cfg.is_active);
      if (needsUpdate) {
        try {
          const updRes = await api.put(`/categories/${found.id}`, {
            name: cfg.name,
            name_en: cfg.name_en,
            is_active: cfg.is_active,
          });
          console.log(`Updated category: ${cfg.name} (${cfg.name_en})`);
          const updated = updRes.data.data || { ...found, ...cfg };
          createdOrExisting[createdOrExisting.length - 1] = updated;
        } catch (e) {
          console.warn(`Update failed for category ${cfg.name}:`, e.response?.data || e.message);
        }
      }
      continue;
    }

    // Create
    try {
      const createRes = await api.post('/categories', {
        name: cfg.name,
        name_en: cfg.name_en,
        is_active: cfg.is_active
      });
      const cat = createRes.data?.data;
      createdOrExisting.push(cat);
      categoryNameToId.set(cfg.name, cat.id);
      console.log(`Created category: ${cfg.name} (${cfg.name_en})`);
    } catch (e) {
      console.error(`Create failed for category ${cfg.name}:`, e.response?.data || e.message);
      throw e;
    }
  }

  // Sort update：使用 categoryNameToId 确保按配置名精确映射
  const sortPayload = {
    categories: categoriesConfig.map(cfg => ({ id: categoryNameToId.get(cfg.name), sort_order: cfg.sort_order }))
  };
  try {
    await api.put('/categories/sort', sortPayload);
    console.log('Category sort order updated.');
  } catch (e) {
    console.warn('Failed to update category sort order:', e.response?.data || e.message);
  }

  return createdOrExisting;
}

async function syncMenuItems(token) {
  logStep('Sync Menu Items from iOS MenuConfig.swift');
  const menuItems = parseMenuItemsFromSwift();
  
  if (menuItems.length === 0) {
    console.warn('No menu items found to sync');
    return;
  }

  const api = axios.create({
    baseURL: `${BASE_URL}/api/menu`,
    headers: { Authorization: `Bearer ${token}` },
    timeout: 20000
  });

  let created = 0, updated = 0, errors = 0;

  for (const item of menuItems) {
    try {
      // 构造图片URL（自动识别扩展名）
      const imageUrl = resolveImageUrl(item.imageName);
      
      // 构造菜单项数据（仅在存在时发送可选字段，避免触发类型校验）
      const menuItemData = {
        name: item.name,
        name_en: item.englishName,
        description: item.description,
        description_en: item.englishDescription,
        price: item.price,
        category_id: item.categoryId,
        is_available: item.isAvailable,
        is_featured: item.categoryName === '推荐',
        spice_level: item.isSpicy ? 2 : 0,
        sort_order: 0
      };

      if (imageUrl) {
        menuItemData.image_url = imageUrl;
      }
      if (item.ingredientDescription) {
        // 路由校验期望为字符串，模型层会 JSON.stringify 存储
        menuItemData.ingredients = item.ingredientDescription;
      }

      const createRes = await api.post('/items', menuItemData);
      console.log(`Created: ${item.name} (${item.englishName})`);
      created++;
    } catch (e) {
      console.warn(`Failed to create ${item.name}:`, e.response?.data?.message || e.message);
      errors++;
    }
  }

  console.log(`Menu items sync completed. Created: ${created}, Errors: ${errors}`);
}

function parseMenuItemsFromSwift() {
  const swiftPath = path.resolve(PROJECT_ROOT, 'CMB250716', 'Config', 'MenuConfig.swift');
  if (!fs.existsSync(swiftPath)) {
    console.warn('MenuConfig.swift not found at', swiftPath);
    return [];
  }
  
  const content = fs.readFileSync(swiftPath, 'utf8');
  const items = [];
  
  // 解析价格映射
  const priceMap = parsePriceConfigMap(content);

  // 分类映射
  const categoryMap = {
    '.recommended': '推荐',
    '.promotion': '促销', 
    '.combo': '套餐',
    '.main': '主菜',
    '.side': '配菜',
    '.chicken': '炸鸡',
    '.drinks': '饮品'
  };

  // 解析 MenuItem 构造函数调用（尽量贪婪匹配内部参数，直到遇到下一行以 ")" 结束）
  const menuItemRegex = /MenuItem\s*\(\s*([\s\S]*?)\)\s*,?/g;
  let match;
  
  while ((match = menuItemRegex.exec(content)) !== null) {
    try {
      const itemContent = match[1];
      const item = parseMenuItemProperties(itemContent, categoryMap, priceMap);
      if (item && item.name && item.categoryId && typeof item.price === 'number') {
        items.push(item);
      }
    } catch (e) {
      console.warn('Failed to parse menu item:', e.message);
    }
  }
  
  console.log(`Parsed ${items.length} menu items from MenuConfig.swift`);
  return items;
}

function parsePriceConfigMap(swiftContent) {
  const map = {};
  // 提取 PriceConfig 结构体块
  const structRegex = /struct\s+PriceConfig\s*\{([\s\S]*?)\}/m;
  const sm = swiftContent.match(structRegex);
  if (!sm) return map;
  const body = sm[1];
  // 支持多种声明方式：let/var，static，类型注解可有可无
  const lineRegex = /(static\s+)?let\s+([A-Za-z0-9_]+)\s*(?::\s*Double)?\s*=\s*([0-9]+(?:\.[0-9]+)?)/g;
  let m;
  while ((m = lineRegex.exec(body)) !== null) {
    const key = m[2];
    const val = parseFloat(m[3]);
    if (!Number.isNaN(val)) {
      map[key] = val;
    }
  }
  const count = Object.keys(map).length;
  console.log(`Loaded ${count} prices from PriceConfig`);
  return map;
}

function parseMenuItemProperties(itemContent, categoryMap, priceMap) {
  const props = {};
  
  // 简单属性解析
  const patterns = {
    name: /name:\s*([^,\n]+)/,
    englishName: /englishName:\s*([^,\n]+)/,
    description: /description:\s*"([^"]+)"/,
    englishDescription: /englishDescription:\s*"([^"]+)"/,
    priceNumber: /price:\s*([0-9.]+)/,
    priceToken: /price:\s*PriceConfig\.([A-Za-z0-9_]+)/,
    category: /category:\s*(\.[\w]+)/,
    imageName: /(?:imageName|realImageName):\s*"([^"]+)"/,
    isAvailable: /isAvailable:\s*(true|false)/,
    isSpicy: /isSpicy:\s*(true|false)/,
    ingredientDescription: /ingredientDescription:\s*"([^"]+)"/
  };

  for (const [key, pattern] of Object.entries(patterns)) {
    const match = itemContent.match(pattern);
    if (match) {
      if (key === 'priceNumber') {
        props.price = parseFloat(match[1]);
      } else if (key === 'priceToken') {
        const token = match[1];
        if (priceMap && Object.prototype.hasOwnProperty.call(priceMap, token)) {
          props.price = priceMap[token];
        }
      } else if (key === 'isAvailable' || key === 'isSpicy') {
        props[key] = match[1] === 'true';
      } else if (key === 'name' || key === 'englishName') {
        // 处理字符串常量引用
        let value = match[1].trim();
        if (value.startsWith('AppStrings.')) {
          // 仅做占位，避免为空导致校验失败
          value = key === 'name' ? '菜品名称' : 'Menu Item';
        } else {
          value = value.replace(/^\"/, '').replace(/\"$/, '');
        }
        props[key] = value;
      } else if (key === 'priceNumber' || key === 'priceToken') {
        // 已在上面处理
      } else {
        props[key] = match[1];
      }
    }
  }

  // 映射分类
  if (props.category && categoryMap[props.category]) {
    const categoryName = categoryMap[props.category];
    props.categoryName = categoryName;
    props.categoryId = categoryNameToId.get(categoryName);
  }

  return props;
}

function ensureDir(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

function resolveImageUrl(imageName) {
  if (!imageName) return null;
  const exts = ['.png', '.jpg', '.jpeg'];
  for (const ext of exts) {
    const full = path.join(UPLOADS_DIR, `${imageName}${ext}`);
    if (fs.existsSync(full)) {
      return `/uploads/menu-images/${imageName}${ext}`;
    }
  }
  return null;
}

function pickBestImage(files) {
  // Prefer @3x, then @2x, else first
  const sorted = files.sort((a, b) => {
    const score = (f) => (/@3x\./.test(f) ? 3 : /@2x\./.test(f) ? 2 : 1);
    return score(b) - score(a);
  });
  return sorted[0];
}

function listImageSetFiles(imagesetPath) {
  const files = fs.readdirSync(imagesetPath)
    .filter(f => !f.startsWith('Contents') && /\.(png|jpg|jpeg)$/i.test(f));
  return files;
}

function extractMenuImageNames() {
  logStep('Extract image names from iOS MenuConfig.swift');
  const swiftPath = path.resolve(PROJECT_ROOT, 'CMB250716', 'Config', 'MenuConfig.swift');
  if (!fs.existsSync(swiftPath)) {
    console.warn('MenuConfig.swift not found at', swiftPath);
    return [];
  }
  const content = fs.readFileSync(swiftPath, 'utf8');
  const names = new Set();
  const re1 = /imageName\s*:\s*"([^"]+)"/g;
  const re2 = /realImageName\s*:\s*"([^"]+)"/g;
  let m;
  while ((m = re1.exec(content)) !== null) {
    names.add(m[1]);
  }
  while ((m = re2.exec(content)) !== null) {
    names.add(m[1]);
  }
  const arr = Array.from(names);
  console.log(`Found ${arr.length} image names in MenuConfig.swift`);
  return arr;
}

function findImagesetPathForName(baseName) {
  const dirName = `${baseName}.imageset`;
  const candidate = path.join(ASSETS_DIR, dirName);
  if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
    return candidate;
  }
  return null;
}

function copyMenuImages(imageNames) {
  logStep('Copy menu images to backend/uploads/menu-images');
  ensureDir(UPLOADS_DIR);
  let copied = 0;
  let missing = 0;
  for (const name of imageNames) {
    const imagesetPath = findImagesetPathForName(name);
    if (!imagesetPath) {
      console.warn(`Imageset not found for: ${name}`);
      missing++;
      continue;
    }
    const files = listImageSetFiles(imagesetPath);
    if (files.length === 0) {
      console.warn(`No image files inside imageset: ${name}`);
      missing++;
      continue;
    }
    const best = pickBestImage(files);
    const src = path.join(imagesetPath, best);
    const ext = path.extname(best);
    const dest = path.join(UPLOADS_DIR, `${name}${ext}`);
    try {
      fs.copyFileSync(src, dest);
      console.log(`Copied ${name}${ext}`);
      copied++;
    } catch (e) {
      console.warn(`Copy failed for ${name}:`, e.message);
    }
  }
  console.log(`Image copy done. Copied: ${copied}, Missing: ${missing}`);
}

// 清理B端前端的所有菜单项，然后重新创建
async function cleanupDuplicateMenuItems(token) {
  logStep('清理B端前端的所有菜单项');
  console.log('Using token:', token.substring(0, 15) + '...');
  
  const api = axios.create({
    baseURL: `${BASE_URL}/api/menu`,
    headers: { Authorization: `Bearer ${token}` },
    timeout: 30000 // 增加超时时间
  });

  try {
    // 测试API连接
    console.log('测试API连接...');
    try {
      const testResponse = await api.get('/categories');
      console.log('API连接成功，分类数量:', testResponse.data.data?.length || 0);
    } catch (testErr) {
      console.error('API连接测试失败:', testErr.message);
      if (testErr.response) {
        console.error('响应状态:', testErr.response.status);
        console.error('响应数据:', JSON.stringify(testErr.response.data));
      }
      throw new Error('API连接失败，无法继续清理');
    }
    
    // 获取B端前端的所有菜单项（处理分页）
    console.log('开始获取所有菜单项...');
    let allItems = [];
    let page = 1;
    let hasMorePages = true;
    const limit = 100; // 每页获取更多项
    
    while (hasMorePages) {
      console.log(`获取第 ${page} 页菜单数据...`);
      let response;
      try {
        response = await api.get('/items', { 
          params: { page, limit },
          timeout: 30000 // 增加超时时间
        });
      } catch (pageErr) {
        console.error(`获取第 ${page} 页时出错:`, pageErr.message);
        if (pageErr.response) {
          console.error('响应状态:', pageErr.response.status);
          console.error('响应数据:', JSON.stringify(pageErr.response.data));
        }
        break; // 出错时停止获取更多页
      }
      
      // 确保我们正确处理API返回的数据结构
      const items = response.data.data?.items || [];
      const pagination = response.data.data?.pagination;
      
      console.log(`第 ${page} 页: 获取到 ${items.length} 个菜单项`);
      
      if (items.length === 0) {
        console.log('没有更多菜单项，停止分页');
        hasMorePages = false;
      } else {
        allItems = allItems.concat(items);
        console.log(`当前总计: ${allItems.length} 个菜单项`);
        
        // 检查是否有更多页
        if (pagination) {
          console.log(`分页信息: 第 ${pagination.page}/${pagination.pages} 页，共 ${pagination.total} 项`);
          if (page >= pagination.pages) {
            console.log('已到达最后一页，停止分页');
            hasMorePages = false;
          } else {
            page++;
          }
        } else {
          console.log('未找到分页信息，停止分页');
          hasMorePages = false;
        }
      }
    }
    
    console.log(`B端前端总共有 ${allItems.length} 个菜单项`);
    
    // 删除所有菜单项
    console.log('开始删除所有菜单项...');
    let deletedCount = 0;
    let failedCount = 0;
    
    for (const item of allItems) {
      try {
        console.log(`删除菜单项: ${item.name} (ID: ${item.id})`);
        await api.delete(`/items/${item.id}`);
        deletedCount++;
        
        // 每删除10个项目，显示一次进度
        if (deletedCount % 10 === 0) {
          console.log(`已删除 ${deletedCount}/${allItems.length} 个菜单项`);
        }
      } catch (e) {
        console.error(`删除菜单项 ${item.name} (ID: ${item.id}) 失败:`, e.message);
        failedCount++;
      }
    }
    
    console.log(`清理完成。成功删除 ${deletedCount} 个菜单项，失败 ${failedCount} 个。`);
    
    // 重置菜单项自增ID
    console.log('尝试重置菜单项自增ID...');
    try {
      // 调用后端API端点重置自增ID
      const resetResponse = await axios.post(`${BASE_URL}/api/admin/reset-menu-items-id`, {}, {
        headers: { Authorization: `Bearer ${token}` },
        timeout: 30000
      });
      
      if (resetResponse.data && resetResponse.data.success) {
        console.log('菜单项自增ID重置成功！');
        console.log(`之前的菜单项数量: ${resetResponse.data.data?.previous_count || '未知'}`);
        console.log(`新的自增ID起始值: ${resetResponse.data.data?.new_auto_increment || 1}`);
      } else {
        console.warn('菜单项自增ID重置可能未成功:', resetResponse.data?.message || '未知原因');
      }
    } catch (resetErr) {
      console.error('重置菜单项自增ID失败:', resetErr.message);
      if (resetErr.response) {
        console.error('响应状态:', resetErr.response.status);
        console.error('响应数据:', JSON.stringify(resetErr.response.data));
      }
    }
    
  } catch (e) {
    console.error('清理菜单项时出错:', e.message);
    if (e.response) {
      console.error('响应状态:', e.response.status);
      console.error('响应数据:', JSON.stringify(e.response.data));
    }
    console.error('堆栈跟踪:', e.stack);
  }
}

// 检查B端前端菜单项是否与APP前端一致
async function checkMenuItemsConsistency(token) {
  logStep('检查APP前端和B端前端菜单项一致性');
  const menuItems = parseMenuItemsFromSwift();
  
  if (menuItems.length === 0) {
    console.warn('APP前端未找到菜单项');
    return;
  }

  const api = axios.create({
    baseURL: `${BASE_URL}/api/menu`,
    headers: { Authorization: `Bearer ${token}` },
    timeout: 30000
  });

  try {
    // 创建一个映射，用于去重，确保每个菜品名称只处理一次
    // 使用菜品名称作为键，因为名称是唯一的
    console.log('对APP前端菜单项进行去重...');
    const uniqueMenuItems = new Map();
    menuItems.forEach(item => {
      // 只保留每个名称的第一个菜品项
      if (!uniqueMenuItems.has(item.name)) {
        uniqueMenuItems.set(item.name, item);
      }
    });
    
    // 将Map转换回数组
    const deduplicatedMenuItems = Array.from(uniqueMenuItems.values());
    console.log(`去重后: ${deduplicatedMenuItems.length} 个唯一菜单项 (原始数量: ${menuItems.length})`);
    
    // 获取B端前端的菜单项（检查是否有菜单项）
    console.log('检查B端前端是否有菜单项...');
    const response = await api.get('/items', { params: { page: 1, limit: 1 } });
    const pagination = response.data.data?.pagination;
    const totalItems = pagination?.total || 0;
    
    console.log(`B端前端当前有 ${totalItems} 个菜单项`);
    
    if (totalItems > 0) {
      console.log('B端前端已有菜单项，跳过添加步骤');
      return;
    }
    
    // B端前端没有菜单项，添加唯一的菜单项
    console.log(`开始添加 ${deduplicatedMenuItems.length} 个唯一菜单项到B端前端...`);
    let addedCount = 0;
    let failedCount = 0;
    
    for (const item of deduplicatedMenuItems) {
      try {
        // 构造图片URL（自动识别扩展名）
        const imageUrl = resolveImageUrl(item.imageName);
        
        // 构造菜单项数据
        const menuItemData = {
          name: item.name,
          name_en: item.englishName,
          description: item.description,
          description_en: item.englishDescription,
          price: item.price,
          category_id: item.categoryId,
          is_available: item.isAvailable !== false, // 默认可用
          is_featured: item.categoryName === '推荐',
          spice_level: item.isSpicy ? 2 : 0,
          sort_order: 0
        };

        if (imageUrl) {
          menuItemData.image_url = imageUrl;
        }
        if (item.ingredientDescription) {
          menuItemData.ingredients = item.ingredientDescription;
        }

        await api.post('/items', menuItemData);
        console.log(`添加菜单项: ${item.name} (${item.englishName})`);
        addedCount++;
        
        // 每添加10个项目，显示一次进度
        if (addedCount % 10 === 0) {
          console.log(`已添加 ${addedCount}/${deduplicatedMenuItems.length} 个菜单项`);
        }
      } catch (e) {
        console.warn(`添加菜单项 ${item.name} 失败:`, e.response?.data?.message || e.message);
        failedCount++;
      }
    }
    
    console.log(`菜单项添加完成。成功: ${addedCount}，失败: ${failedCount}`);
  } catch (e) {
    console.error('检查菜单项一致性时出错:', e.response?.data || e.message);
  }
}

async function main() {
  try {
    const token = await loginAndGetToken();
    await ensureCategories(token);

    // 首先清理B端前端的重复菜单项
    console.log('\n==== 第一步：清理B端前端的重复菜单项 ====');
    await cleanupDuplicateMenuItems(token);

    // Extract and copy images first（可控）
    if (SYNC_IMAGES) {
      console.log('\n==== 第二步：同步菜单图片 ====');
      const names = extractMenuImageNames();
      if (names.length > 0) {
        copyMenuImages(names);
      } else {
        console.warn('No image names extracted; skipping copy');
      }
    } else {
      console.log('Skip copying images due to SYNC_IMAGES=false');
    }

    // Sync menu items（可控）
    if (SYNC_ITEMS) {
      console.log('\n==== 第三步：检查并添加缺失的菜单项 ====');
      // 不再调用syncMenuItems，只检查并同步缺失的菜单项
      // 避免创建重复项
      await checkMenuItemsConsistency(token);
    } else {
      console.log('Skip syncing menu items due to SYNC_ITEMS=false');
    }

    console.log('\nAll tasks completed.');
  } catch (err) {
    console.error('Sync failed:', err.message || err);
    process.exitCode = 1;
  }
}

if (require.main === module) {
  main();
}